/*****        as608驱动模块
****    1.as608指纹模块与串口3连接 通过串口发送的指令代码实现各种驱动功能
****	2.wak线（蓝线）——--外部中断PA0
****	  wak线:感应电平输出,默认高电平有效
****	3.设置USART3的波特率为57600
*****/

#include "as608.h"
#include "queue.h"
#include "SysTick.h"
#include "usart.h" 
#include "as608_test.h"
#include "stm32f10x_it.h"
#include "JZ.h"
/*接收数据延时*/
#define AS608_DELAY_MS(x)     SysTick_Delay_Ms(x)

uint32_t AS608_Addr = 0xFFFFFFFF;             /*指纹识别模块默认地址*/


static void NVIC_Configuration(void);
static void AS608_SendData(uint8_t data);
static void AS608_PackHead(void);
static void SendFlag(uint8_t flag);
static void SendLength(uint16_t length);
static void Sendcmd(uint8_t cmd);
static void SendCheck(uint16_t check);
uint16_t PS_GetImage(void);


//-----配置嵌套向量中断控制器NVIC
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  // 嵌套向量中断控制器组选择 
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //组2
  
  // 配置USART中断源的NVIC 
  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  //NVIC线路使能	
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				
  // 抢断优先级
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  // 子优先级 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  //将结构体的值写入寄存器
  NVIC_Init(&NVIC_InitStructure);
	
	
  // 配置EXTI中断源的NVIC
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; 
  // 使能中断 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	
    // 抢断优先级
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  // 配置子优先级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  // 初始化配置EXTI0
  NVIC_Init(&NVIC_InitStructure); 
}


//------配置EXTI和USART3外部中断
void AS608_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; 
	EXTI_InitTypeDef EXTI_InitStructure;
	USART_InitTypeDef USART_InitStructure;
  
	//使能串口GPIOA、GPIOB和AFIO时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
	//使能APB1总线上的串口外设 USART3时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
			
	//初始化GPIO----配置PA0的输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;  //浮空输入IN_FLOATING 下拉输入IPD  上拉IPU
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//AFIO外部中断引脚选择----PA0映射到EXTI0上
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); 
	
	//配置EXTI----外部中断的事件和边沿触发
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; // 上升沿和下降沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
	
	//配置 NVIC 中断
	NVIC_Configuration();
	
	
	//将USART3 Tx的GPIO配置为复用式推挽输出模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);  

	//将USART3 Rx的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//配置串口3的工作参数
	//配置波特率
	USART_InitStructure.USART_BaudRate = AS608_USART_BAUDRATE; //115200
	//配置 针数据字长
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	//配置停止位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	//配置校验位
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	//配置硬件流控制
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	//配置工作模式，收发一起
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	//完成串口的初始化配置
	USART_Init(USART3, &USART_InitStructure);
	
	//使能串口接收中断
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);	//开启串口接收数据中断
	USART_ITConfig(USART3, USART_IT_IDLE, ENABLE ); //开启串口总线空闲中断 	
	
	//使能串口3
	USART_Cmd(USART3, ENABLE);	

}

//----------AS608_USART串口向指纹模块传递数据 
//data;传输的数据
static void AS608_SendData(uint8_t data)
{
  USART_SendData(USART3,data);
  while(USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET); 
}


//------AS608_USART串口向指纹模块命令包头格式 
//发送包头和地址
static void AS608_PackHead(void)
{ 
  /*包头*/
  AS608_SendData(0xEF);
  AS608_SendData(0x01);	
  
  /*指纹模块地址*/
  AS608_SendData(AS608_Addr>>24);
  AS608_SendData(AS608_Addr>>16);	
  AS608_SendData(AS608_Addr>>8);
  AS608_SendData(AS608_Addr);	
}



//----------发送包标识
//flag:包标识位
static void SendFlag(uint8_t flag)
{
  AS608_SendData(flag);
}



//-----------发送包长度
//length:包长度
static void SendLength(uint16_t length)
{
	AS608_SendData(length>>8);
  AS608_SendData(length);
}


//-------------发送指令码
//cmd;指令码

static void Sendcmd(uint8_t cmd)
{
	AS608_SendData(cmd);
}


//---------发送校验和
//check:检查位

static void SendCheck(uint16_t check)
{
	AS608_SendData(check>>8);
	AS608_SendData(check);
}

//---------从缓冲区读出确认码(解析应答包)
//*i:返回值（确认码）

uint16_t  ReturnFlag( uint16_t *i)
{
   QUEUE_DATA_TYPE *rx_data;
  
   rx_data = cbRead(&rx_queue);  /*从缓冲区读取数据，进行处理*/
    
   if(rx_data != NULL)           /*缓冲队列非空*/
  { 
		/*打印环行接收到的数据*/
    QUEUE_DEBUG_ARRAY((uint8_t*)rx_data->head,rx_data->len);
		
    *i=((uint16_t)(*(rx_data->head+9)));     /*确认码*/
		
	  cbReadFinish(&rx_queue);    /*使用完数据必须调用cbReadFinish更新读指针*/
	  
		return *i;
  }
	else
  {	
	  *i=0xff;
		
	  return *i;
  }
}


//-----------探测手指，探测到后录入指纹图像存于 ImageBuffer
//确认码=00H 表示录入成功；确认码=01H 表示收包有错；
//确认码=02H 表示传感器上无手指；确认码=03H 表示录入不成功 

uint16_t PS_GetImage(void)
{
  uint16_t temp;
  uint16_t sure,p=0;
	
             uint8_t *data;
	
	AS608_DELAY_MS(3000);       /*给指纹输入动作预留3s时间*/
	
	AS608_PackHead();	//发送包头和地址
	SendFlag(0x01);             /*命令包标识01H---1byte*/
	SendLength(0x03);	//发送包长度03H---2byte
	Sendcmd(0x01);              /*录指纹指令码01H---1byte*/
  temp=0x01+0x03+0x01;	//校验和
	SendCheck(temp);	

  AS608_DELAY_MS(500);        /*等待指纹识别模块处理数据*/
  
	sure=ReturnFlag(&p); //接收应答包
  
  return  sure;
	
}



//----------将ImageBuffer中的原始图像生成指纹特征文件存于CHARBUFFER1或CHARBUFFER2
//BufferID(特征缓冲区号)
//确认码=00H 表示生成特征成功；确认码=01H 表示收包有错；
//确认码=06H 表示指纹图像太乱而生不成特征；确认码=07H 表示指纹图像正常，但特征点太少而生不成特征；
//确认码=15H 表示图像缓冲区内没有有效原始图而生不成图像

uint16_t PS_GenChar(uint8_t BufferID)
{
  uint16_t temp;
  uint16_t  sure,p=0;
 
  AS608_PackHead();
  SendFlag(0x01);          
  SendLength(0x04);
  Sendcmd(0x02);              /*生成特征指令*/   
  AS608_SendData(BufferID);
  temp = 0x01+0x04+0x02+BufferID;
  SendCheck(temp);
	
  AS608_DELAY_MS(600);
	
  sure=ReturnFlag(&p);
  
  return  sure;
}


//--------检查STM32与指纹模块的通信连接
//PS_Addr指纹模块地址
//返回值0通讯成功;1表示通讯不成功

uint16_t PS_Connect(uint32_t *PS_Addr)
{
	QUEUE_DATA_TYPE *rx_data;	
	
	AS608_PackHead();
	AS608_SendData(0X01);
	AS608_SendData(0X00);
	AS608_SendData(0X00);
	
  AS608_DELAY_MS(100);
	
	rx_data = cbRead(&rx_queue);  /*从缓冲区读取数据，进行处理*/ 
	if(rx_data != NULL)           /*缓冲队列非空*/
	{ 
		/*打印环行接收到的数据*/
		QUEUE_DEBUG_ARRAY((uint8_t*)rx_data->head,rx_data->len);
		
		if(/*判断是不是模块返回的应答包*/
   			*(rx_data->head)	== 0XEF
				  && *(rx_data->head+1)==0X01
				  && *(rx_data->head+6)==0X07)  
		  {
			printf("as608 addr:0x%x%x%x%x",*(rx_data->head+2),
																						      *(rx_data->head+3),
																						      *(rx_data->head+4),
																					   	    *(rx_data->head+5));
			n+=16;
			OLED_ShowString(0,n,"as608 addr:",6);
			OLED_ShowHexNum(70,n,*(rx_data->head+2),2,6);
			OLED_ShowHexNum(74,n,*(rx_data->head+3),2,6);
			OLED_ShowHexNum(78,n,*(rx_data->head+4),2,6);
			OLED_ShowHexNum(82,n,*(rx_data->head+5),2,6);
			OLED_Update();
			n+=8;
		  }
			cbReadFinish(&rx_queue);  /*使用完数据必须调用cbReadFinish更新读指针*/
		  
			return 0;	
	}	
	
  return 1;		
}


//--------精确比对 CHARBUFFER1与CHARBUFFER2中的特征文件
//确认码=00H 表示指纹匹配；确认码=01H 表示收包有错；确认码=08H 表示指纹不匹配

uint16_t PS_Match(void)
{
	uint16_t temp;
  uint16_t  sure,p=0;
	
	AS608_PackHead();
	SendFlag(0x01);
	SendLength(0x03);
	Sendcmd(0x03);                /*精确比对指令*/
	temp = 0x01+0x03+0x03;
	SendCheck(temp);
	
  AS608_DELAY_MS(500);
	
  sure=ReturnFlag(&p);
  
  return  sure;

}


//-----------将CHARBUFFER1与CHARBUFFER2 中的特征文件合并生成模板，
//结果存于CHARBUFFER1与CHARBUFFER2。
//确认码=00H 表示合并成功；确认码=01H 表示收包有错；
//确认码=0aH 表示合并失败（两枚指纹不属于同一手指）
uint16_t PS_RegModel(void)
{
	uint16_t temp;
  uint16_t sure,p=0;
  	
	AS608_PackHead();
	SendFlag(0x01);
	SendLength(0x03);
	Sendcmd(0x05);                /*合并特征指令*/
	temp = 0x01+0x03+0x05;
	SendCheck(temp);
	
  AS608_DELAY_MS(500);
	
  sure=ReturnFlag(&p);
  
  return  sure;

}


//-----------键盘输入ID
//返回输入值
uint32_t GET_NUM(void)
{
	uint32_t num;
	//scanf("%d", &num);
	while( !(num = MatrixKey_GetValue_add()));
	AS608_INFO("input ID: ");
	printf("%d\n",num);
	OLED_ShowNum(0,44,num,2,6);
	OLED_Update();
	return num;
}



//------------将 CHARBUFFER1 或 CHARBUFFER2 中的模板文件存到 PageID 号flash 数据库位置。
//BufferID:缓冲区号，
//PageID:指纹库位置号
//确认码=00H 表示储存成功；确认码=01H 表示收包有错；
//确认码=0bH 表示 PageID 超出指纹库范围；确认码=18H 表示写 FLASH 出错
uint16_t PS_StoreChar(uint8_t BufferID,uint16_t PageID)
{
	uint16_t temp;
  uint16_t sure,p=0;
 
	AS608_PackHead();
	SendFlag(0x01);
	SendLength(0x06);
	Sendcmd(0x06);                /*存储模板指令*/
	AS608_SendData(BufferID);
  AS608_SendData(PageID>>8);
	AS608_SendData(PageID);
	temp = 0x01+0x06+0x06+BufferID
	       +(PageID>>8)+(uint8_t)PageID;
	SendCheck(temp);
	
	AS608_DELAY_MS(500);
	
  sure=ReturnFlag(&p);
  
  return  sure;

	
}

//--------------以CHARBUFFER1或CHARBUFFER2中的特征文件高速搜索整个或部分指纹库
//BufferID:缓冲区号
//StartPage:起始页
//PageNum:页数
//p:传递指针
//ensure:确认字,*p:页码（相配指纹模板）

uint16_t PS_HighSpeedSearch(uint8_t BufferID,uint16_t StartPage,uint16_t PageNum,uint16_t *p)
{
	uint16_t temp;
  uint16_t ensure;
  QUEUE_DATA_TYPE *rx_data;
	
	AS608_PackHead();
	SendFlag(0x01);
	SendLength(0x08);
	Sendcmd(0x1b);                 /*高速搜索指纹库指令*/
	AS608_SendData(BufferID);
	AS608_SendData(StartPage>>8);
	AS608_SendData(StartPage);
	AS608_SendData(PageNum>>8);
	AS608_SendData(PageNum);
	temp = 0x01+0x08+0x1b+BufferID
	       +(StartPage>>8)+(uint8_t)StartPage
	       +(PageNum>>8)+(uint8_t)PageNum;
	SendCheck(temp);
	
 	AS608_DELAY_MS(500);
	
  rx_data = cbRead(&rx_queue);  /*从缓冲区读取数据，进行处理*/
  if(rx_data != NULL)           /*缓冲队列非空*/
  {
		/*打印环行接收到的数据*/
	  QUEUE_DEBUG_ARRAY((uint8_t*)rx_data->head,rx_data->len);
    
    ensure=((uint16_t)(*(rx_data->head+9)));   /*确认码*/
    
    /*返回页码（相匹配的指纹模板ID）*/
	  *p=((*(rx_data->head+10))<<8)+(*(rx_data->head+11));
    
	  cbReadFinish(&rx_queue);    /*使用完数据必须调用cbReadFinish更新读指针*/
    
	  return ensure;
  }
	else
	{	
	  ensure=0xff;
    
	  return ensure;
	}
}




//-------------删除 flash 数据库中指定ID号开始的N个指纹模板
//PageID:指纹库模板号
//N:删除的模板个数
//确认码=00H 表示删除模板成功；确认码=01H 表示收包有错；
//确认码=10H 表示删除模板失败

uint16_t PS_DeletChar(uint16_t PageID,uint16_t N)
{
	uint16_t temp;
  uint16_t sure,p=0;
 
	
	AS608_PackHead();
	SendFlag(0x01);//命令包标识
	SendLength(0x07);
	Sendcmd(0x0C);                /*删除指定指纹模板指令*/
	AS608_SendData(PageID>>8);
  AS608_SendData(PageID);
	AS608_SendData(N>>8);
	AS608_SendData(N);
	temp = 0x01+0x07+0x0C
	       +(PageID>>8)+(uint8_t)PageID
	       +(N>>8)+(uint8_t)N;
	SendCheck(temp);
	
	AS608_DELAY_MS(400);
	
	sure=ReturnFlag(&p);
  
  return  sure;

	
}

//-----------删除 flash 数据库中所有指纹模板
//确认码=00H 表示清空成功；确认码=01H 表示收包有错；确认码=11H 表示清空失败
uint16_t  PS_Empty(void)
{
	uint16_t temp;
  uint16_t sure,p=0;
 
	
	AS608_PackHead();
	SendFlag(0x01);//命令包标识
	SendLength(0x03);
	Sendcmd(0x0D);
	temp = 0x01+0x03+0x0D;
	SendCheck(temp);
	
	AS608_DELAY_MS(400);
	
  sure=ReturnFlag(&p);
  
  return  sure;

}



//--------显示错误信息
//ensure:确认码
void  ShowErrMessage( uint16_t  ensure) 
{
  switch(ensure)
	{
    case  0x00:
			AS608_INFO("OK");
		break;
		
	  case  0x01:
			AS608_INFO("Packet receiving error");
		break;
		
	  case  0x02:
	    AS608_INFO("NO Find FRP");
		break;
		
	  case  0x03:
	    AS608_INFO("input FRP LOSE");
		break;
		
	  case  0x04:
	    AS608_INFO("images dry light LOSE");
		break;
	  
		case  0x05:
	    AS608_INFO("images wet mushy LOSE");
		break;
		
	  case  0x06:
	    AS608_INFO("images messy LOSE");
		break;
		
	  case  0x07:
	    AS608_INFO("image area small LOSE");
		
		break;
		
	  case  0x08:
	    AS608_INFO("FRP mismatch");
		break;
		
	  case  0x09:
      AS608_INFO("compare libs LOSE");
		break;
		
		case  0x0a:
	    AS608_INFO("Feature merge failure");
		break;
		
		case  0x0b:
      AS608_INFO("addr num beyond libs");
		break;
		
		case  0x10:
	    AS608_INFO("del template LOSE");
		break;
		
		case  0x11:
      AS608_INFO("clear FRP libs LOSE");
		break;	
		
		case  0x15:
		  AS608_INFO("NO original drawing image");
		break;
		
		case  0x18:
		  AS608_INFO("read-write FLASH ERROR");
		break;
		
		case  0x19:
	    AS608_INFO("Undefined ERROR");
		break;
		
		case  0x1a:
	    AS608_INFO("Invalid register number");
		break;
		
		case  0x1b:
			AS608_INFO("Register set content ERROR");
		break;
		
		case  0x1c:
		  AS608_INFO("notepad page number ERROR");
		break;
		
		case  0x1f:
      AS608_INFO("Fingerprint database full");
		break;
		
		case  0x20:
      AS608_INFO("address error");
		break;
		
		default :
      AS608_INFO("module return ERROR");
		break;	
  }

}







